﻿Imports System.Reflection

Public NotInheritable Class GamePad
    Inherits UserControl
    Implements IDisposable

    Private WithEvents upButton As GamepadButton
    Private WithEvents downButton As GamepadButton
    Private WithEvents leftButton As GamepadButton
    Private WithEvents rightButton As GamepadButton

    Private _gamepadType As enGamepadType
    Public Enum enGamepadType
        DIRECTIONAL_2_LEFT_RIGHT = 0        'un pad con 2 bottoni direzionali (sinistra, destra)
        DIRECTIONAL_2_UP_DOWN = 1           'un pad con 2 bottoni direzionali (su, giù)
        DIRECTIONAL_3_UP_DOWN_RIGHT = 2     'un pad con 3 bottoni direzionali (su, giù, destra)
        DIRECTIONAL_3_UP_DOWN_LEFT = 3      'un pad con 3 bottoni direzionali (su, giù, sinistra)
        DIRECTIONAL_3_LEFT_RIGHT_UP = 4     'un pad con 3 bottoni direzionali (sinistra, destra, su)
        DIRECTIONAL_3_LEFT_RIGHT_DOWN = 5   'un pad con 3 bottoni direzionali (sinistra, destra, giù)
        DIRECTIONAL_4 = 6                   'un pad con 4 bottoni direzionali (su, giù, sinistra, destra)
        ACTION_2_LEFT_RIGHT = 7             'un pad con 2 tasti "azione" A e D (sinistra, destra)
        ACTION_2_UP_DOWN = 8                'un pad con 2 tasti "azione" W e S (su, giù)
        ACTION_3_UP_DOWN_RIGHT = 9          'un pad con 3 tasti "azione" W S D
        ACTION_3_UP_DOWN_LEFT = 10          'un pad con 3 tasti "azione" W A S
        ACTION_3_LEFT_RIGHT_UP = 11         'un pad con 3 tasti "azione" A W D
        ACTION_3_LEFT_RIGHT_DOWN = 12       'un pad con 3 tasti "azione" A S D
        ACTION_4 = 13                       'un pad con 4 tasti "azione" W A S D
    End Enum

    Public Enum enButtonType
        UP_BUTTON = 0
        DOWN_BUTTON = 1
        LEFT_BUTTON = 2
        RIGHT_BUTTON = 3
        W_BUTTON = 4
        A_BUTTON = 5
        S_BUTTON = 6
        D_BUTTON = 7
    End Enum

#Region "PROPERTIES"

    ''' <summary>
    ''' Restituisce o imposta il tipo di gamepad da visualizzare
    ''' </summary>
    ''' <value>Tipo enumerato per identificare i tipi di gamepad predefiniti</value>
    Public Property GamepadType As enGamepadType
        Get
            Return _gamepadType
        End Get
        Set(value As enGamepadType)
            _gamepadType = value
        End Set
    End Property

#End Region

#Region "EVENT DECLARATIONS"

    Public Event ButtonPressed(buttonType As enButtonType)
    Public Event ButtonReleased(buttonType As enButtonType)

#End Region

#Region "EVENTS"

    Public Sub New(gamepadType As enGamepadType)

        ' Chiamata richiesta dalla finestra di progettazione.
        InitializeComponent()

        Me.GamepadType = gamepadType

        'creo i bottoni utilizzando la classe derivata da Button
        'li posiziono ed assegno loro lo stile
        Me.upButton = New GamepadButton
        Canvas.SetLeft(upButton, 64)
        Me.upButton.Style = Me.Resources("GamePadButtonStyle")

        Me.downButton = New GamepadButton
        Canvas.SetLeft(downButton, 64)
        Canvas.SetTop(downButton, 130)
        Me.downButton.Style = Me.Resources("GamePadButtonStyle")

        Me.leftButton = New GamepadButton
        Canvas.SetLeft(leftButton, 0)
        Canvas.SetTop(leftButton, 65)
        Me.leftButton.Style = Me.Resources("GamePadButtonStyle")

        Me.rightButton = New GamepadButton
        Canvas.SetLeft(rightButton, 129)
        Canvas.SetTop(rightButton, 65)
        Me.rightButton.Style = Me.Resources("GamePadButtonStyle")

        Me.gamePadCanvas.Children.Add(upButton)
        Me.gamePadCanvas.Children.Add(downButton)
        Me.gamePadCanvas.Children.Add(leftButton)
        Me.gamePadCanvas.Children.Add(rightButton)

        'imposto le immagini sui bottoni
        Dim upButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.upButton.png"))
        Dim downButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.downButton.png"))
        Dim leftButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.leftButton.png"))
        Dim rightButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.rightButton.png"))

        Dim wButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.wButton.png"))
        Dim sButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.sButton.png"))
        Dim aButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.aButton.png"))
        Dim dButtonStream As New MemoryRandomAccessStream(Me.GetType.GetTypeInfo.Assembly.GetManifestResourceStream("MMGameLibrary2D.dButton.png"))

        'Up Button
        Dim source As New BitmapImage
        Dim img As New Image
        Select Case Me.GamepadType
            Case enGamepadType.ACTION_2_UP_DOWN, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_LEFT, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                source.SetSourceAsync(wButtonStream)
            Case enGamepadType.DIRECTIONAL_2_UP_DOWN, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                source.SetSourceAsync(upButtonStream)
            Case Else
                source = Nothing
        End Select
        img.Source = source
        Me.upButton.Content = img

        'Down Button
        source = New BitmapImage
        img = New Image
        Select Case Me.GamepadType
            Case enGamepadType.ACTION_2_UP_DOWN, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_UP_DOWN_LEFT, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                source.SetSourceAsync(sButtonStream)
            Case enGamepadType.DIRECTIONAL_2_UP_DOWN, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                source.SetSourceAsync(downButtonStream)
            Case Else
                source = Nothing
        End Select
        img.Source = source
        Me.downButton.Content = img

        'Left Button
        source = New BitmapImage
        img = New Image
        Select Case Me.GamepadType
            Case enGamepadType.ACTION_2_LEFT_RIGHT, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_LEFT
                source.SetSourceAsync(aButtonStream)
            Case enGamepadType.DIRECTIONAL_2_LEFT_RIGHT, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT
                source.SetSourceAsync(leftButtonStream)
            Case Else
                source = Nothing
        End Select
        img.Source = source
        Me.leftButton.Content = img

        'Right Button
        source = New BitmapImage
        img = New Image
        Select Case Me.GamepadType
            Case enGamepadType.ACTION_2_LEFT_RIGHT, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                source.SetSourceAsync(dButtonStream)
            Case enGamepadType.DIRECTIONAL_2_LEFT_RIGHT, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                source.SetSourceAsync(rightButtonStream)
            Case Else
                source = Nothing
        End Select
        img.Source = source
        Me.rightButton.Content = img

    End Sub

    Private Sub Buttons_ButtonPressed(sender As Object) Handles upButton.ButtonPressed, downButton.ButtonPressed, leftButton.ButtonPressed, rightButton.ButtonPressed

        If sender Is upButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_UP_DOWN, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonPressed(enButtonType.UP_BUTTON)
                Case enGamepadType.ACTION_2_UP_DOWN, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_LEFT, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonPressed(enButtonType.W_BUTTON)
            End Select
        ElseIf sender Is downButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_UP_DOWN, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonPressed(enButtonType.DOWN_BUTTON)
                Case enGamepadType.ACTION_2_UP_DOWN, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_UP_DOWN_LEFT, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonPressed(enButtonType.S_BUTTON)
            End Select
        ElseIf sender Is leftButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_LEFT_RIGHT, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT
                    RaiseEvent ButtonPressed(enButtonType.LEFT_BUTTON)
                Case enGamepadType.ACTION_2_LEFT_RIGHT, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_LEFT
                    RaiseEvent ButtonPressed(enButtonType.A_BUTTON)
            End Select
        ElseIf sender Is rightButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_LEFT_RIGHT, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonPressed(enButtonType.RIGHT_BUTTON)
                Case enGamepadType.ACTION_2_LEFT_RIGHT, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonPressed(enButtonType.D_BUTTON)
            End Select
        End If

    End Sub

    Private Sub Buttons_ButtonReleased(sender As Object) Handles upButton.ButtonReleased, downButton.ButtonReleased, leftButton.ButtonReleased, rightButton.ButtonReleased

        If sender Is upButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_UP_DOWN, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonReleased(enButtonType.UP_BUTTON)
                Case enGamepadType.ACTION_2_UP_DOWN, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_LEFT, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonReleased(enButtonType.W_BUTTON)
            End Select
        ElseIf sender Is downButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_UP_DOWN, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonReleased(enButtonType.DOWN_BUTTON)
                Case enGamepadType.ACTION_2_UP_DOWN, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_UP_DOWN_LEFT, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonReleased(enButtonType.S_BUTTON)
            End Select
        ElseIf sender Is leftButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_LEFT_RIGHT, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_LEFT
                    RaiseEvent ButtonReleased(enButtonType.LEFT_BUTTON)
                Case enGamepadType.ACTION_2_LEFT_RIGHT, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_LEFT
                    RaiseEvent ButtonReleased(enButtonType.A_BUTTON)
            End Select
        ElseIf sender Is rightButton Then
            Select Case Me.GamepadType
                Case enGamepadType.DIRECTIONAL_2_LEFT_RIGHT, enGamepadType.DIRECTIONAL_4, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_DOWN, enGamepadType.DIRECTIONAL_3_LEFT_RIGHT_UP, enGamepadType.DIRECTIONAL_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonReleased(enButtonType.RIGHT_BUTTON)
                Case enGamepadType.ACTION_2_LEFT_RIGHT, enGamepadType.ACTION_4, enGamepadType.ACTION_3_LEFT_RIGHT_DOWN, enGamepadType.ACTION_3_LEFT_RIGHT_UP, enGamepadType.ACTION_3_UP_DOWN_RIGHT
                    RaiseEvent ButtonReleased(enButtonType.D_BUTTON)
            End Select
        End If

    End Sub

#End Region

#Region "IDisposable Support"
    Private disposedValue As Boolean ' Per rilevare chiamate ridondanti

    ' IDisposable
    Protected Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                upButton = Nothing
                downButton = Nothing
                leftButton = Nothing
                rightButton = Nothing
            End If

            ' TODO: liberare risorse non gestite (oggetti non gestiti) ed eseguire l'override del seguente Finalize().
            ' TODO: impostare campi di grandi dimensioni su null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: eseguire l'override di Finalize() solo se Dispose(ByVal disposing As Boolean) dispone del codice per liberare risorse non gestite.
    'Protected Overrides Sub Finalize()
    '    ' Non modificare questo codice. Inserire il codice di pulizia in Dispose(ByVal disposing As Boolean).
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' Questo codice è aggiunto da Visual Basic per implementare in modo corretto il modello Disposable.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Non modificare questo codice. Inserire il codice di pulizia in Dispose(disposing As Boolean).
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

#Region "CLASSES"

    ''' <summary>
    ''' Classe che eredita dalla classe Button ed implementa gli eventi ButtonPressed e ButtonReleased
    ''' </summary>
    Class GamepadButton
        Inherits Button

        Event ButtonPressed(sender As Object)
        Event ButtonReleased(sender As Object)

        Public Sub New()
            MyBase.New()

            Me.Width = 70
            Me.Height = 70

        End Sub

        Protected Overrides Sub OnPointerPressed(e As PointerRoutedEventArgs)
            MyBase.OnPointerPressed(e)

            RaiseEvent ButtonPressed(Me)

            e.Handled = True
        End Sub

        Protected Overrides Sub OnPointerReleased(e As PointerRoutedEventArgs)
            MyBase.OnPointerReleased(e)

            RaiseEvent ButtonReleased(Me)

            e.Handled = True
        End Sub

    End Class

#End Region

End Class
